// 安装 mysql => npm i mysql -S
const mysql = require('mysql');
// 引入 Node 核心模块 crypto 进行加密操作
const crypto = require('crypto');
// 安装 jsonwebtoken => npm i jsonwebtoken -S
const jwt = require('jsonwebtoken');
// 定义一个加密盐值常量
const SECRET_KEY = 'case sign in secret';

/**
 * 连接数据库，执行 SQL 查询
 * @param {string} sql 要执行的 SQL 语句
 * @param {array} params SQL 语句中的参数
 */
const query = (sql, params = []) => {
    // 使用 mysql 创建连接数据库的配置信息
    const con = mysql.createConnection({
        host: 'localhost',
        port: 3306,
        user: 'root',
        password: 'root',
        database: 'case-sign-in',
    });

    // 开始连接数据
    con.connect((error) => {
        if (error) return console.log('数据库连接失败', error.message);
    });

    // 执行 SQL 语句
    return new Promise((resolve, reject) => {
        // 执行异步操作
        con.query(sql, params, (error, result) => {
            if (error) return reject(error);
            resolve(result);
        });

        // 告诉 MySQL 服务器，我已经执行完 SQL 了，后面也没了，你给我关闭吧
        con.end();
    });
};

/**
 * 密码加密函数
 * @param {string} raw_password 要加密的密码
 */
const passwordEncoder = (raw_password) => {
    // 调用 Node 核心模块 crypto 进行加密
    return crypto
        .createHmac('sha256', SECRET_KEY)
        .update(raw_password)
        .digest('hex');
};

/**
 * 生成 Token 令牌的函数
 * @param {object} obj 要加密保存到 token 中的信息
 */
const genToken = (obj) => {
    // 第一个参数：要保存的信息
    // 第二个参数：加密盐值
    // 第三个参数：配置对象，一般我们只配置 token 的有效期
    return jwt.sign(obj, SECRET_KEY, { expiresIn: '2h' });
};

/**
 * 用于校验 token 的合法性
 * @param {string} token 服务器签发的 token
 */
const checkToken = (token) => {
    try {
        return jwt.verify(token, SECRET_KEY);
    } catch (error) {
        console.log(error);
        return false;
    }
};

/**
 * 转成 Date 日期字符串
 * @param {Date} date JS 的 Date 对象
 */
const toLocalDateString = (date) => {
    if (date instanceof Date) {
        const Y = date.getFullYear();
        const M = String(date.getMonth() + 1).padStart(2, '0');
        const D = String(date.getDate()).padStart(2, '0');
        return `${Y}-${M}-${D}`;
    }
    return null;
};

module.exports = {
    query,
    passwordEncoder,
    genToken,
    checkToken,
    toLocalDateString,
};
